home *** CD-ROM | disk | FTP | other *** search
/ Mac Magazin/MacEasy 11 / Mac Magazin and MacEasy Magazine CD - Issue 11.iso / Sharewarebibliothek / Entwickler / WASTE 1.1b1 Distribution / WASTE Source / WEHighLevelEditing.p < prev    next >
Text File  |  1995-06-01  |  37KB  |  1,450 lines

  1. unit WEHighLevelEditing;
  2.  
  3. { WASTE PROJECT: }
  4. { High-Level Editing Routines }
  5.  
  6. { Copyright © 1993-1994 Marco Piovanelli }
  7. { All Rights Reserved }
  8.  
  9. interface
  10.     uses
  11.         WELowLevelEditing;
  12.  
  13.     const
  14.  
  15. { action kinds }
  16.  
  17.         weAKNone = 0;                                { null action }
  18.         weAKUnspecified = 1;                    { action of unspecified nature }
  19.         weAKTyping = 2;                            { some text has been typed in }
  20.         weAKCut = 3;                                { the selection range has been cut }
  21.         weAKPaste = 4;                                { something has been pasted }
  22.         weAKClear = 5;                                { the selection range has been deleted }
  23.         weAKDrag = 6;                                { drag and drop operation }
  24.         weAKSetStyle = 7;                        { some style has been applied to a text range }
  25.  
  26. { action flags }
  27.  
  28.         weAFIsRedo = $0001;                    { action saves edit state prior to a WEUndo call }
  29.         weAFDontSaveText = $0002;        { don't save text }
  30.         weAFDontSaveStyles = $0004;        { don't save styles }
  31.         weAFDontSaveSoup = $0008;        { don't save embedded object information }
  32.  
  33.     type
  34.  
  35.         WEActionKind = Integer;
  36.         WEActionFlags = Integer;
  37.  
  38. { a WEAction record is used to record a single editing operation on a WE instance, }
  39. { like typing some text, cutting or pasting.  A linked list of WEAction records might }
  40. { be used to implement multiple undo. }
  41.  
  42.         WEActionHandle = ^WEActionPtr;
  43.         WEActionPtr = ^WEAction;
  44.         WEAction = record
  45.                 hOwner: WEHandle;                    { handle to associated WE instance }
  46.                 hNext: WEActionHandle;            { used to keep a linked list of actions }
  47.                 hText: Handle;                            { handle to saved text }
  48.                 hStyles: Handle;                        { handle to saved styles }
  49.                 hSoup: Handle;                            { handle to saved "soup" }
  50.                 delRangeStart: LongInt;            { start of range to delete }
  51.                 delRangeLength: LongInt;            { length of range to delete }
  52.                 insRangeLength: LongInt;            { length of range to insert }
  53.                 hiliteStart: LongInt;                    { start of range to hilite }
  54.                 hiliteEnd: LongInt;                    { end of range to hilite }
  55.                 actionKind: WEActionKind;        { identifies event that caused this action to be pushed }
  56.                 actionFlags: WEActionFlags;        { miscellaneous flags }
  57.             end;  { WEAction }
  58.  
  59. { high-level editing functions }
  60.  
  61.     procedure WEKey (key: Char;
  62.                                     modifiers: Integer;
  63.                                     hWE: WEHandle);
  64.     function WEInsert (textPtr: Ptr;
  65.                                     textLength: LongInt;
  66.                                     hStyles: StScrpHandle;
  67.                                     hSoup: Handle;
  68.                                     hWE: WEHandle): OSErr;
  69.     function WEInsertObject (objectType: OSType;
  70.                                     objectDataHandle: Handle;
  71.                                     objectSize: Point;
  72.                                     hWE: WEHandle): OSErr;
  73.     function WEDelete (hWE: WEHandle): OSErr;
  74.     function WECut (hWE: WEHandle): OSErr;
  75.     function WEPaste (hWE: WEHandle): OSErr;
  76.     function WESetStyle (mode: Integer;
  77.                                     var ts: WETextStyle;
  78.                                     hWE: WEHandle): OSErr;
  79.     function WEUseStyleScrap (hStyles: StScrpHandle;
  80.                                     hWE: WEHandle): OSErr;
  81.  
  82. { high-level Undo functions }
  83.  
  84.     function WEUndo (hWE: WEHandle): OSErr;
  85.     procedure WEClearUndo (hWE: WEHandle);
  86.     function WEGetUndoInfo (var redoFlag: Boolean;
  87.                                     hWE: WEHandle): WEActionKind;
  88.  
  89. { keeping track of changes }
  90.  
  91.     function WEGetModCount (hWE: WEHandle): LongInt;
  92.     procedure WEResetModCount (hWE: WEHandle);
  93.  
  94. { actions }
  95.  
  96.     function WENewAction (rangeStart, rangeEnd: LongInt;
  97.                                     newTextLength: LongInt;
  98.                                     actionKind: WEActionKind;
  99.                                     actionFlags: WEActionFlags;
  100.                                     hWE: WEHandle;
  101.                                     var hAction: WEActionHandle): OSErr;
  102.     procedure WEDisposeAction (hAction: WEActionHandle);
  103.     function WEDoAction (hAction: WEActionHandle): OSErr;
  104.  
  105. { low-level routines for directly manipulating }
  106. { the action stack associated with a given WE instance }
  107.  
  108.     function WEGetActionStack (hWE: WEHandle): WEActionHandle;
  109.     function WEPushAction (hAction: WEActionHandle): OSErr;
  110.  
  111. { miscellaneous }
  112.  
  113.     function WECanPaste (hWE: WEHandle): Boolean;
  114.     procedure _WEAdjustUndoRange (moreBytes: LongInt;
  115.                                     hWE: WEHandle);
  116.     function WEIsTyping (hWE: WEHandle): Boolean;
  117.  
  118. implementation
  119.     uses
  120.         Scrap, WEScraps;
  121.  
  122.     function WEGetActionStack (hWE: WEHandle): WEActionHandle;
  123.     begin
  124.         WEGetActionStack := WEActionHandle(hWE^^.hActionStack);
  125.     end;  { WEGetActionStack }
  126.  
  127.     function WEPushAction (hAction: WEActionHandle): OSErr;
  128.         var
  129.             pWE: WEPtr;
  130.             hLast: WEActionHandle;
  131.     begin
  132.         WEPushAction := noErr;
  133.  
  134. { find the last action in the given stack }
  135.         hLast := hAction;
  136.         while (hLast^^.hNext <> nil) do
  137.             hLast := hLast^^.hNext;
  138.  
  139. { prepend hAction in front of the action stack }
  140.         pWE := hAction^^.hOwner^;
  141.         hLast^^.hNext := WEActionHandle(pWE^.hActionStack);
  142.         pWE^.hActionStack := Handle(hAction);
  143.  
  144.     end;  { WEPushAction }
  145.  
  146.     function WENewAction (rangeStart, rangeEnd: LongInt;
  147.                                     newTextLength: LongInt;
  148.                                     actionKind: WEActionKind;
  149.                                     actionFlags: WEActionFlags;
  150.                                     hWE: WEHandle;
  151.                                     var hAction: WEActionHandle): OSErr;
  152.         label
  153.             0, 1;
  154.         var
  155.             pAction: WEActionPtr;
  156.             err: OSErr;
  157.     begin
  158.  
  159. { allocate a new action record }
  160.         err := _WEAllocate(SizeOf(WEAction), kAllocClear, hAction);
  161.         if (err <> noErr) then
  162.             goto 1;
  163.  
  164. { lock it down }
  165.         HLock(Handle(hAction));
  166.         pAction := hAction^;
  167.  
  168. { fill in the fields }
  169.         pAction^.hOwner := hWE;
  170.         pAction^.delRangeStart := rangeStart;
  171.         pAction^.delRangeLength := newTextLength;
  172.         pAction^.insRangeLength := rangeEnd - rangeStart;
  173.         pAction^.actionKind := actionKind;
  174.         pAction^.actionFlags := actionFlags;
  175.  
  176. { remember selection range }
  177.         WEGetSelection(pAction^.hiliteStart, pAction^.hiliteEnd, hWE);
  178.  
  179. { allocate a handle to hold the text to be saved, unless otherwise specified }
  180.         if (BAND(actionFlags, weAFDontSaveText) = 0) then
  181.             begin
  182.                 err := _WEAllocate(0, kAllocTemp, pAction^.hText);
  183.                 if (err <> noErr) then
  184.                     goto 1;
  185.             end;
  186.  
  187. { allocate a handle to hold the styles to be saved, unless otherwise specified }
  188.         if (BAND(actionFlags, weAFDontSaveStyles) = 0) then
  189.             begin
  190.                 err := _WEAllocate(0, kAllocTemp, pAction^.hStyles);
  191.                 if (err <> noErr) then
  192.                     goto 1;
  193.             end;
  194.  
  195. { allocate a handle to hold the "soup" to be saved, unless otherwise specified }
  196.         if (BAND(actionFlags, weAFDontSaveSoup) = 0) then
  197.             begin
  198.                 err := _WEAllocate(0, kAllocTemp, pAction^.hSoup);
  199.                 if (err <> noErr) then
  200.                     goto 1;
  201.             end;
  202.  
  203. { make a copy of text range }
  204.         err := WECopyRange(rangeStart, rangeEnd, pAction^.hText, pAction^.hStyles, pAction^.hSoup, hWE);
  205.         if (err <> noErr) then
  206.             goto 1;
  207.  
  208. { unlock action record }
  209.         HUnlock(Handle(hAction));
  210.  
  211. { skip clean-up section }
  212.         goto 0;
  213.  
  214. 1:
  215. { clean up }
  216.         _WEForgetHandle(pAction^.hText);
  217.         _WEForgetHandle(pAction^.hStyles);
  218.         _WEForgetHandle(pAction^.hSoup);
  219.         _WEForgetHandle(hAction);
  220.  
  221. 0:
  222. { return result code }
  223.         WENewAction := err;
  224.  
  225.     end;  { WENewAction }
  226.  
  227.     procedure WEDisposeAction (hAction: WEActionHandle);
  228.         var
  229.             pAction: WEActionPtr;
  230.             hNext: WEActionHandle;
  231.     begin
  232.         while (hAction <> nil) do
  233.             begin
  234.  
  235. { lock the action record }
  236.                 HLock(Handle(hAction));
  237.                 pAction := hAction^;
  238.                 hNext := pAction^.hNext;
  239.  
  240. { throw away text, styles and soup }
  241.                 _WEForgetHandle(pAction^.hText);
  242.                 _WEForgetHandle(pAction^.hStyles);
  243.                 _WEForgetHandle(pAction^.hSoup);
  244.  
  245. { throw away the action record itself }
  246.                 DisposeHandle(Handle(hAction));
  247.  
  248. { repeat the same sequence with all linked actions }
  249.                 hAction := hNext;
  250.  
  251.             end;  { while }
  252.     end;  { WEDisposeAction }
  253.  
  254.     procedure WEForgetAction (var hAction: WEActionHandle);
  255.         var
  256.             theAction: WEActionHandle;
  257.     begin
  258.         theAction := hAction;
  259.         if (theAction <> nil) then
  260.             begin
  261.                 hAction := nil;
  262.                 WEDisposeAction(theAction);
  263.             end;
  264.     end;  { WEForgetAction }
  265.  
  266.     function WEDoAction (hAction: WEActionHandle): OSErr;
  267.         label
  268.             1;
  269.         var
  270.             hRedoAction: WEActionHandle;
  271.             pAction: WEActionPtr;
  272.             hWE: WEHandle;
  273.             pWE: WEPtr;
  274.             offset, delOffset, insOffset: LongInt;
  275.             redrawStart, redrawEnd: LongInt;
  276.             saveActionLock, saveWELock, saveTextLock: Boolean;
  277.             err: OSErr;
  278.     begin
  279.  
  280. { sanity check: make sure hAction isn't NIL }
  281.         if (hAction = nil) then
  282.             begin
  283.                 WEDoAction := nilHandleErr;
  284.                 Exit(WEDoAction);
  285.             end;
  286.  
  287. { get handle to associated WE instance }
  288.         hWE := hAction^^.hOwner;
  289.  
  290. { lock the WE record }
  291.         saveWELock := _WESetHandleLock(hWE, true);
  292.         pWE := hWE^;
  293.  
  294. { return an error code if this instance is read-only }
  295.         err := weReadOnlyErr;
  296.         if (BTST(pWE^.flags, weFReadOnly)) then
  297.             goto 1;
  298.  
  299. { stop any ongoing inline input session }
  300.         WEStopInlineSession(hWE);
  301.  
  302. { hide selection highlighting and the caret }
  303.         _WEHiliteRange(pWE^.selStart, pWE^.selEnd, hWE);
  304.         if BTST(pWE^.flags, weFCaretVisible) then
  305.             _WEBlinkCaret(hWE);
  306.  
  307.         redrawStart := maxLongInt;
  308.         redrawEnd := 0;
  309.  
  310.         repeat
  311.  
  312. { lock the action record }
  313.             saveActionLock := _WESetHandleLock(hAction, true);
  314.             pAction := hAction^;
  315.             offset := pAction^.delRangeStart;
  316.             delOffset := offset + pAction^.delRangeLength;
  317.             insOffset := offset + pAction^.insRangeLength;
  318.  
  319. { if undo support is enabled, save the range to be affected by this action }
  320.             if (BTST(pWE^.flags, weFUndoSupport)) then
  321.                 if (WENewAction(offset, delOffset, pAction^.insRangeLength, pAction^.actionKind, BXOR(pAction^.actionFlags, weAFIsRedo), hWE, hRedoAction) = noErr) then
  322.                     if (WEPushAction(hRedoAction) <> noErr) then
  323.                         ;
  324.  
  325.             if (pAction^.hText <> nil) then
  326.                 begin
  327.  
  328. { delete the range to replace }
  329.                     err := _WEDeleteRange(offset, delOffset, hWE);
  330.                     if (err <> noErr) then
  331.                         goto 1;
  332.  
  333. { insert the saved text }
  334.                     saveTextLock := _WESetHandleLock(pAction^.hText, true);
  335.                     err := _WEInsertText(offset, pAction^.hText^, pAction^.insRangeLength, hWE);
  336.                     if (_WESetHandleLock(pAction^.hText, saveTextLock)) then
  337.                         ;
  338.                     if (err <> noErr) then
  339.                         goto 1;
  340.  
  341.                 end;
  342.  
  343. { apply the saved styles, if any }
  344.             if (pAction^.hStyles <> nil) then
  345.                 begin
  346.                     err := _WEApplyStyleScrap(offset, insOffset, StScrpHandle(pAction^.hStyles), hWE);
  347.                     if (err <> noErr) then
  348.                         goto 1;
  349.                 end;
  350.  
  351. { the same goes for the soup }
  352.             if (pAction^.hSoup <> nil) then
  353.                 begin
  354.                     err := _WEApplySoup(offset, pAction^.hSoup, hWE);
  355.                     if (err <> noErr) then
  356.                         goto 1;
  357.                 end;
  358.  
  359. { adjust redraw range }
  360.             if (offset < redrawStart) then
  361.                 redrawStart := offset;
  362.             if (insOffset > redrawEnd) then
  363.                 redrawEnd := insOffset;
  364.  
  365. { unlock action record }
  366.             if (_WESetHandleLock(hAction, saveActionLock)) then
  367.                 ;
  368.  
  369. { go to next action }
  370.             hAction := hAction^^.hNext;
  371.  
  372.         until (hAction = nil);
  373.  
  374. { restore the original selection range }
  375.         pWE^.selStart := pAction^.hiliteStart;
  376.         pWE^.selEnd := pAction^.hiliteEnd;
  377.  
  378. { redraw the text }
  379.         err := _WERedraw(redrawStart, redrawEnd, hWE);
  380.         if (err <> noErr) then
  381.             goto 1;
  382.  
  383. { clear result code }
  384.         err := noErr;
  385.  
  386. 1:
  387. { unlock the WE record }
  388.         if (_WESetHandleLock(hWE, saveWELock)) then
  389.             ;
  390.  
  391. { return result code }
  392.         WEDoAction := err;
  393.  
  394.     end;  { WEDoAction }
  395.  
  396.     function WEUndo (hWE: WEHandle): OSErr;
  397.         var
  398.             pWE: WEPtr;
  399.             hAction: WEActionHandle;
  400.             saveWELock: Boolean;
  401.     begin
  402.  
  403. { lock the WE record }
  404.         saveWELock := _WESetHandleLock(hWE, true);
  405.         pWE := hWE^;
  406.  
  407. { "detach" the action stack from the WE instance }
  408.         hAction := WEActionHandle(pWE^.hActionStack);
  409.         pWE^.hActionStack := nil;
  410.  
  411.         if (hAction <> nil) then
  412.             begin
  413.  
  414. { undoing a change _decrements_ the modification count; }
  415. { redoing the change increments it again }
  416.                 if (BAND(hAction^^.actionFlags, weAFIsRedo) <> 0) then
  417.                     pWE^.modCount := pWE^.modCount + 1
  418.                 else
  419.                     pWE^.modCount := pWE^.modCount - 1;
  420.  
  421. { perform the action... }
  422.                 WEUndo := WEDoAction(hAction);
  423.  
  424. { ...and throw it away }
  425.                 WEDisposeAction(hAction);
  426.  
  427.             end
  428.         else
  429.  
  430. { return an error code if the undo buffer is empty }
  431.             WEUndo := weCantUndoErr;
  432.  
  433. { unlock the WE record }
  434.         if (_WESetHandleLock(hWE, saveWELock)) then
  435.             ;
  436.  
  437.     end;  { WEUndo }
  438.  
  439.     procedure WEClearUndo (hWE: WEHandle);
  440.     begin
  441.  
  442. { dispose of the action chain associated with the given WE instance }
  443.         WEForgetAction(WEActionHandle(hWE^^.hActionStack));
  444.  
  445.     end;  { WEClearUndo }
  446.  
  447.     function WEGetUndoInfo (var redoFlag: Boolean;
  448.                                     hWE: WEHandle): WEActionKind;
  449.     begin
  450.         WEGetUndoInfo := weAKNone;        { assume no actions have been saved }
  451.         redoFlag := false;
  452.  
  453.         if (hWE^^.hActionStack <> nil) then
  454.             with WEActionHandle(hWE^^.hActionStack)^^ do
  455.                 begin
  456.                     WEGetUndoInfo := actionKind;
  457.                     redoFlag := (BAND(actionFlags, weAFIsRedo) <> 0);
  458.                 end;
  459.     end;  { WEGetUndoInfo }
  460.  
  461.     function WEGetModCount (hWE: WEHandle): LongInt;
  462.     begin
  463.         WEGetModCount := hWE^^.modCount;
  464.     end;  { WEGetModCount }
  465.  
  466.     procedure WEResetModCount (hWE: WEHandle);
  467.     begin
  468.         hWE^^.modCount := 0;
  469.         WEClearUndo(hWE);
  470.     end;  { WEResetModCount }
  471.  
  472.     procedure _WEAdjustUndoRange (moreBytes: LongInt;
  473.                                     hWE: WEHandle);
  474.         var
  475.             hAction: WEActionHandle;
  476.     begin
  477.         hAction := WEActionHandle(hWE^^.hActionStack);
  478.         if (hAction <> nil) then
  479.             with hAction^^ do
  480.                 delRangeLength := delRangeLength + moreBytes;
  481.     end;  { _WEAdjustUndoRange }
  482.  
  483.     function _WETypeChar (theByte: SignedByte;
  484.                                     hWE: WEHandle): OSErr;
  485.         label
  486.             0, 1;
  487.         var
  488.             pWE: WEPtr;
  489.             db: DoubleByte;
  490.             offset, endOffset, charLength: LongInt;
  491.             err: OSErr;
  492.     begin
  493.         pWE := hWE^;                    { the WE record must be already locked }
  494.         charLength := 1;                { assume 1-byte character by default }
  495.         db.firstByte := theByte;
  496.         offset := pWE^.selStart;
  497.  
  498. { delete current selection, if any }
  499.         err := _WEDeleteRange(offset, pWE^.selEnd, hWE);
  500.         if (err <> noErr) then
  501.             goto 1;
  502.         pWE^.selEnd := offset;        { needed in case we take a premature exit }
  503.  
  504. { make sure the font script is synchronized with the keyboard script }
  505.         _WESynchNullStyle(hWE);
  506.  
  507.         if BTST(pWE^.flags, weFDoubleByte) then
  508.             begin
  509.  
  510. { special processing for double-byte characters }
  511.                 if (pWE^.firstByte <> 0) then
  512.                     begin
  513.  
  514. { if this byte is the second half of a double-byte character, }
  515. { insert the two bytes at the same time (flush the double-byte cache) }
  516.                         db.firstByte := pWE^.firstByte;
  517.                         db.secondByte := theByte;
  518.                         charLength := 2;
  519.                         pWE^.firstByte := 0;
  520.                     end
  521.                 else
  522.  
  523. { if theByte is the first half of a double-byte character, just cache it and exit }
  524.                     if (CallWECharByteProc(@theByte, 0, FontToScript(pWE^.nullStyle.runStyle.tsFont), hWE, pWE^.charByteHook) = smFirstByte) then
  525.                         begin
  526.                             pWE^.firstByte := theByte;
  527.                             goto 0;
  528.                         end;
  529.             end;  { if double-byte script installed }
  530.  
  531. { insert the new character into the text }
  532.         err := _WEInsertText(offset, @db, charLength, hWE);
  533.         if (err <> noErr) then
  534.             goto 1;
  535.  
  536. { adjust undo buffer for the new character }
  537.         _WEAdjustUndoRange(charLength, hWE);
  538.  
  539. { invalid the null style }
  540.         BCLR(pWE^.flags, weFUseNullStyle);
  541.  
  542. { move the insertion point after the new character }
  543.         endOffset := offset + charLength;
  544.         pWE^.selStart := endOffset;
  545.         pWE^.selEnd := endOffset;
  546.  
  547. { redraw the text }
  548.         err := _WERedraw(offset, endOffset, hWE);
  549.         if (err <> noErr) then
  550.             goto 1;
  551.  
  552. 0:
  553. { clear result code }
  554.         err := noErr;
  555.  
  556. 1:
  557. { return result code }
  558.         _WETypeChar := err;
  559.  
  560.     end;  { _WETypeChar }
  561.  
  562.     function _WEBackspace (hWE: WEHandle): OSErr;
  563.  
  564. { this routine is called by WEKey to handle the backspace key }
  565. { the WE record is guaranteed to be already locked }
  566.  
  567.         label
  568.             0, 1;
  569.         var
  570.             pWE: WEPtr;
  571.             pAction: WEActionPtr;
  572.             rangeStart, rangeEnd, charLength: LongInt;
  573.             pChars: WECharsPtr;
  574.             runInfo: WERunInfo;
  575.             saveActionLock: Boolean;
  576.             err: OSErr;
  577.     begin
  578.         pWE := hWE^;
  579.  
  580. { calculate the text range to delete }
  581. { if the selection is non-empty, delete that }
  582.         rangeStart := pWE^.selStart;
  583.         rangeEnd := pWE^.selEnd;
  584.         if (rangeStart = rangeEnd) then
  585.             begin
  586.  
  587. { otherwise the selection is an insertion point }
  588. { do nothing if insertion point is at the beginning of the text }
  589.                 if (rangeStart = 0) then
  590.                     goto 0;
  591.  
  592. { determine the byte-type of the character preceding the insertion point }
  593.                 if (WECharByte(rangeStart - 1, hWE) = smSingleByte) then
  594.                     charLength := 1
  595.                 else
  596.                     charLength := 2;
  597.                 rangeStart := rangeStart - charLength;
  598.  
  599.                 if (pWE^.hActionStack <> nil) then
  600.                     begin
  601.  
  602. { UNDO SUPPORT FOR BACKSPACES }
  603.  
  604. { lock the action record }
  605.                         saveActionLock := _WESetHandleLock(pWE^.hActionStack, true);
  606.                         pAction := WEActionHandle(pWE^.hActionStack)^;
  607.  
  608. { backspaces over the newly entered text aren't a problem }
  609.                         if (pAction^.delRangeLength > 0) then
  610.                             pAction^.delRangeLength := pAction^.delRangeLength - charLength
  611.                         else
  612.                             begin
  613.  
  614. { the hard part comes when backspacing past the new text because }
  615. { the user is about to delete a character not included in the block we saved }
  616.  
  617. { lengthen our saved text handle }
  618.                                 SetHandleSize(pAction^.hText, pAction^.insRangeLength + charLength);
  619.                                 err := MemError;
  620.                                 if (err <> noErr) then
  621.                                     goto 1;
  622.  
  623. { move old contents forward }
  624.                                 pChars := WECharsHandle(pAction^.hText)^;
  625.                                 BlockMoveData(@pChars^[0], @pChars^[charLength], pAction^.insRangeLength);
  626.  
  627. { prepend the character to be deleted to the beginning of our saved text handle }
  628.                                 pChars^[0] := WEGetChar(rangeStart, hWE);
  629.                                 if (charLength = 2) then
  630.                                     pChars^[1] := WEGetChar(rangeStart + 1, hWE);
  631.  
  632. { adjust internal counters }
  633.                                 pAction^.insRangeLength := pAction^.insRangeLength + charLength;
  634.                                 pAction^.delRangeStart := pAction^.delRangeStart - charLength;
  635.  
  636. { get style run info associated with the about-to-be-deleted character }
  637.                                 WEGetRunInfo(rangeStart, runInfo, hWE);
  638.  
  639. { prepend a new style element to our style scrap, if necessary }
  640.                                 err := _WEPrependStyle(pAction^.hStyles, runInfo, charLength);
  641.                                 if (err <> noErr) then
  642.                                     goto 1;
  643.  
  644. { do the same with our object "soup" }
  645.                                 err := _WEPrependObject(pAction^.hSoup, runInfo, charLength);
  646.                                 if (err <> noErr) then
  647.                                     goto 1;
  648.  
  649.                             end;  { if deleting old text }
  650.  
  651. { unlock the action record }
  652.                         if (_WESetHandleLock(pWE^.hActionStack, saveActionLock)) then
  653.                             ;
  654.  
  655.                     end;  { if undo support is enabled }
  656.             end;  { if selection is empty }
  657.  
  658.         err := _WEDeleteRange(rangeStart, rangeEnd, hWE);
  659.         if (err <> noErr) then
  660.             goto 1;
  661.  
  662. { keep track of current selection range }
  663.         pWE^.selStart := rangeStart;
  664.         pWE^.selEnd := rangeStart;
  665.  
  666. { redraw the text }
  667.         err := _WERedraw(rangeStart, rangeStart, hWE);
  668.         if (err <> noErr) then
  669.             goto 1;
  670.  
  671. 0:
  672. { clear result code }
  673.         err := noErr;
  674.  
  675. 1:
  676. { return result code }
  677.         _WEBackspace := err;
  678.  
  679.     end;  { _WEBackspace }
  680.  
  681.     function _WEForwardDelete (hWE: WEHandle): OSErr;
  682.  
  683. { this routine is called by WEKey to handle the forward delete key }
  684. { the WE record is guaranteed to be already locked }
  685.  
  686.         label
  687.             0, 1;
  688.         var
  689.             pWE: WEPtr;
  690.             pAction: WEActionPtr;
  691.             rangeStart, rangeEnd, charLength: LongInt;
  692.             runInfo: WERunInfo;
  693.             db: DoubleByte;
  694.             saveActionLock: Boolean;
  695.             err: OSErr;
  696.     begin
  697.         pWE := hWE^;
  698.  
  699. { calculate the text range to delete }
  700. { if the selection is non-empty, delete that }
  701.         rangeStart := pWE^.selStart;
  702.         rangeEnd := pWE^.selEnd;
  703.         if (rangeStart = rangeEnd) then
  704.             begin
  705.  
  706. { otherwise the selection is an insertion point }
  707. { do nothing if insertion point is at the end of the text }
  708.                 if (rangeStart = pWE^.textLength) then
  709.                     goto 0;
  710.  
  711. { determine the byte-type of the character following the insertion point }
  712.                 if (WECharByte(rangeStart, hWE) = smSingleByte) then
  713.                     charLength := 1
  714.                 else
  715.                     charLength := 2;
  716.                 rangeEnd := rangeStart + charLength;
  717.  
  718.                 if (pWE^.hActionStack <> nil) then
  719.                     begin
  720.  
  721. { UNDO SUPPORT FOR FORWARD DELETE }
  722.  
  723. { lock the action record }
  724.                         saveActionLock := _WESetHandleLock(pWE^.hActionStack, true);
  725.                         pAction := WEActionHandle(pWE^.hActionStack)^;
  726.  
  727. { make a copy of the character about to be deleted }
  728.                         db.firstByte := SignedByte(WEGetChar(rangeStart, hWE));
  729.                         if (charLength = 2) then
  730.                             db.secondByte := SignedByte(WEGetChar(rangeStart + 1, hWE));
  731.  
  732. { append it to the end of our saved text handle }
  733.                         err := PtrAndHand(@db, pAction^.hText, charLength);
  734.                         if (err <> noErr) then
  735.                             goto 1;
  736.  
  737. { get style run info associated with the about-to-be-deleted character }
  738.                         WEGetRunInfo(rangeStart, runInfo, hWE);
  739.  
  740. { append a new style element to our style scrap, if necessary }
  741.                         err := _WEAppendStyle(pAction^.hStyles, runInfo, pAction^.insRangeLength);
  742.                         if (err <> noErr) then
  743.                             goto 1;
  744.  
  745. { do the same with our object soup }
  746.                         err := _WEAppendObject(pAction^.hSoup, runInfo, pAction^.insRangeLength);
  747.                         if (err <> noErr) then
  748.                             goto 1;
  749.  
  750. { adjust internal counters }
  751.                         pAction^.insRangeLength := pAction^.insRangeLength + charLength;
  752.  
  753. { unlock the action record }
  754.                         if (_WESetHandleLock(pWE^.hActionStack, saveActionLock)) then
  755.                             ;
  756.  
  757.                     end;  { if undo support is enabled }
  758.             end;  { if selection is empty }
  759.  
  760.         err := _WEDeleteRange(rangeStart, rangeEnd, hWE);
  761.         if (err <> noErr) then
  762.             goto 1;
  763.  
  764. { keep track of current selection range }
  765.         pWE^.selStart := rangeStart;
  766.         pWE^.selEnd := rangeStart;
  767.  
  768. { redraw the text }
  769.         err := _WERedraw(rangeStart, rangeStart, hWE);
  770.         if (err <> noErr) then
  771.             goto 1;
  772.  
  773. 0:
  774. { clear result code }
  775.         err := noErr;
  776.  
  777. 1:
  778. { return result code }
  779.         _WEForwardDelete := err;
  780.  
  781.     end;  { _WEForwardDelete }
  782.  
  783.     function WEIsTyping (hWE: WEHandle): Boolean;
  784.         var
  785.             pWE: WEPtr;
  786.     begin
  787.  
  788. { return TRUE if we're tracking a typing sequence in the specified WE instance }
  789.  
  790.         WEIsTyping := false;            { assume we aren't }
  791.         pWE := hWE^;                    { the WE record must already be locked }
  792.  
  793. { there must be an undo buffer }
  794.         if (pWE^.hActionStack = nil) then
  795.             Exit(WEIsTyping);
  796.  
  797.         with WEActionHandle(pWE^.hActionStack)^^ do
  798.             begin
  799.  
  800. { the action kind must be "typing" and the redo flag must be clear }
  801.                 if (actionKind <> weAKTyping) then
  802.                     Exit(WEIsTyping);
  803.                 if (BAND(actionFlags, weAFIsRedo) <> 0) then
  804.                     Exit(WEIsTyping);
  805.  
  806. { finally, the selection range mustn't have moved since the last WEKey }
  807.                 if ((pWE^.selStart = pWE^.selEnd) and (pWE^.selStart = delRangeStart + delRangeLength)) then
  808.                     WEIsTyping := true;
  809.             end;  { with }
  810.     end;  { WEIsTyping }
  811.  
  812.     procedure WEKey (key: Char;
  813.                                     modifiers: Integer;
  814.                                     hWE: WEHandle);
  815.         var
  816.             pWE: WEPtr;
  817.             hAction: WEActionHandle;
  818.             saveWELock: Boolean;
  819.             err: OSErr;
  820.     begin
  821.         err := noErr;
  822.  
  823. { lock the WE record }
  824.         saveWELock := _WESetHandleLock(hWE, true);
  825.         pWE := hWE^;
  826.  
  827. { hide the caret if it's showing }
  828.         if BTST(pWE^.flags, weFCaretVisible) then
  829.             _WEBlinkCaret(hWE);
  830.  
  831. { hide the cursor (it will show again as soon as it's moved) }
  832.         ObscureCursor;
  833.  
  834. { dispatch on key class (arrow keys, printable characters, backspace) }
  835.         if ((ORD(key) >= kArrowLeft) and (ORD(key) <= kArrowDown)) then
  836.             _WEDoArrowKey(ORD(key), modifiers, hWE)
  837.         else
  838.  
  839. { non-arrow keys modify the text, so make sure editing is allowed }
  840.             if (not BTST(pWE^.flags, weFReadOnly)) then
  841.                 begin
  842.  
  843. { are we tracking a typing sequence? }
  844.                     if (WEIsTyping(hWE) = false) then
  845.                         begin
  846.  
  847. { nope; so start a new one }
  848. { increment modification count }
  849.                             pWE^.modCount := pWE^.modCount + 1;
  850.  
  851. { if undo support is enabled, create a new action to keep track of the typing }
  852.                             if (BTST(pWE^.flags, weFUndoSupport)) then
  853.                                 begin
  854.                                     WEClearUndo(hWE);
  855.                                     if (WENewAction(pWE^.selStart, pWE^.selEnd, 0, weAKTyping, 0, hWE, hAction) = noErr) then
  856.                                         if (WEPushAction(hAction) <> noErr) then
  857.                                             ;
  858.                                 end;
  859.                         end;  { if WEIsTyping }
  860.  
  861.                     if (ORD(key) = kBackspace) then
  862.                         err := _WEBackspace(hWE)
  863.                     else if (ORD(key) = kForwardDelete) then
  864.                         err := _WEForwardDelete(hWE)
  865.                     else
  866.                         err := _WETypeChar(ORD(key), hWE);
  867.  
  868.                 end;  { if not read-only }
  869.  
  870. { unlock the WE record }
  871.         if (_WESetHandleLock(hWE, saveWELock)) then
  872.             ;
  873.  
  874. (*WEKey := err;*)
  875.  
  876.     end;  { WEKey }
  877.  
  878.     function WEInsert (textPtr: Ptr;
  879.                                     textLength: LongInt;
  880.                                     hStyles: StScrpHandle;
  881.                                     hSoup: Handle;
  882.                                     hWE: WEHandle): OSErr;
  883.         label
  884.             1;
  885.         var
  886.             pWE: WEPtr;
  887.             offset, endOffset: LongInt;
  888.             hAction: WEActionHandle;
  889.             intPasteAction: Integer;
  890.             saveWELock: Boolean;
  891.             space: SignedByte;
  892.             err: OSErr;
  893.     begin
  894.  
  895. { lock the WE record }
  896.         saveWELock := _WESetHandleLock(hWE, true);
  897.         pWE := hWE^;
  898.         offset := pWE^.selStart;
  899.  
  900. { return an error code if this instance is read-only }
  901.         err := weReadOnlyErr;
  902.         if (BTST(pWE^.flags, weFReadOnly)) then
  903.             goto 1;
  904.  
  905. { stop any ongoing inline input session }
  906.         WEStopInlineSession(hWE);
  907.  
  908. { increment modification count }
  909.         pWE^.modCount := pWE^.modCount + 1;
  910.  
  911. { if undo support is enabled, save current selection range }
  912.         if (BTST(pWE^.flags, weFUndoSupport)) then
  913.             begin
  914.                 WEClearUndo(hWE);
  915.                 if (WENewAction(offset, pWE^.selEnd, textLength, weAKUnspecified, 0, hWE, hAction) = noErr) then
  916.                     if (WEPushAction(hAction) <> noErr) then
  917.                         ;
  918.             end;
  919.  
  920. { delete current selection }
  921.         err := _WEDeleteRange(offset, pWE^.selEnd, hWE);
  922.         if (err <> noErr) then
  923.             goto 1;
  924.  
  925. { insert the new text at the insertion point }
  926.         err := _WEInsertText(offset, textPtr, textLength, hWE);
  927.         if (err <> noErr) then
  928.             goto 1;
  929.         endOffset := offset + textLength;
  930.  
  931.         if (hStyles <> nil) then
  932.             begin
  933.  
  934. { if a style scrap was supplied, apply it to the newly inserted text }
  935.                 err := _WEApplyStyleScrap(offset, endOffset, hStyles, hWE);
  936.                 if (err <> noErr) then
  937.                     goto 1;
  938.             end;
  939.  
  940.         if (hSoup <> nil) then
  941.             begin
  942.  
  943. { if an object soup was supplied, apply it to the newly inserted text }
  944.                 err := _WEApplySoup(offset, hSoup, hWE);
  945.                 if (err <> noErr) then
  946.                     goto 1;
  947.             end;
  948.  
  949. { determine whether an extra space should be added before or after the inserted text }
  950.         intPasteAction := _WEIntelligentPaste(offset, endOffset, hWE);
  951.  
  952. { add the extra space, if necessary }
  953.         if (intPasteAction <> weDontAddSpaces) then
  954.             begin
  955.  
  956.                 space := kSpace;
  957.                 if (intPasteAction = weAddSpaceOnLeftSide) then
  958.                     err := _WEInsertText(offset, @space, 1, hWE)
  959.                 else
  960.                     err := _WEInsertText(endOffset, @space, 1, hWE);
  961.                 if (err <> noErr) then
  962.                     goto 1;
  963.                 endOffset := endOffset + 1;
  964.  
  965. { adjust undo buffer (if any) for the extra space }
  966.                 _WEAdjustUndoRange(1, hWE);
  967.  
  968.             end;
  969.  
  970. { invalid the null style }
  971.         BCLR(pWE^.flags, weFUseNullStyle);
  972.  
  973. { move the insertion point at the end of the inserted text }
  974.         pWE^.selStart := endOffset;
  975.         pWE^.selEnd := endOffset;
  976.  
  977. { redraw the text }
  978.         err := _WERedraw(offset, endOffset, hWE);
  979.         if (err <> noErr) then
  980.             goto 1;
  981.  
  982. { clear result code }
  983.         err := noErr;
  984.  
  985. 1:
  986. { return result code }
  987.         WEInsert := err;
  988.  
  989. { unlock the WE record }
  990.         if (_WESetHandleLock(hWE, saveWELock)) then
  991.             ;
  992.  
  993.     end;  { WEInsert }
  994.  
  995.     function WEInsertObject (objectType: OSType;
  996.                                     objectDataHandle: Handle;
  997.                                     objectSize: Point;
  998.                                     hWE: WEHandle): OSErr;
  999.         label
  1000.             1;
  1001.         var
  1002.             pWE: WEPtr;
  1003.             hAction: WEActionHandle;
  1004.             offset, endOffset: LongInt;
  1005.             ts: WETextStyle;
  1006.             marker: SignedByte;
  1007.             saveWELock: Boolean;
  1008.             err: OSErr;
  1009.     begin
  1010.         _WEBlockClr(@ts, SizeOf(ts));
  1011.  
  1012. { lock the WE record }
  1013.         saveWELock := _WESetHandleLock(hWE, true);
  1014.         pWE := hWE^;
  1015.         offset := pWE^.selStart;
  1016.  
  1017. { return an error code if this instance is read-only }
  1018.         err := weReadOnlyErr;
  1019.         if (BTST(pWE^.flags, weFReadOnly)) then
  1020.             goto 1;
  1021.  
  1022. { stop any ongoing inline input session }
  1023.         WEStopInlineSession(hWE);
  1024.  
  1025. { call the 'new' handler to initialize private object storage (if any) }
  1026. { and to calculate the default size for this object }
  1027.         err := _WENewObject(objectType, objectDataHandle, hWE, WEObjectDescHandle(ts.tsObject));
  1028.         if (err <> noErr) then
  1029.             goto 1;
  1030.  
  1031. { use the specified object size, unless it is (0, 0), in which case keep the default size }
  1032.         if (LongInt(objectSize) <> 0) then
  1033.             WEObjectDescHandle(ts.tsObject)^^.objectSize := objectSize;
  1034.  
  1035. { increment modification count }
  1036.         pWE^.modCount := pWE^.modCount + 1;
  1037.  
  1038. { if undo support is enabled, save current selection range }
  1039.         if (BTST(pWE^.flags, weFUndoSupport)) then
  1040.             begin
  1041.                 WEClearUndo(hWE);
  1042.                 if (WENewAction(offset, pWE^.selEnd, 1, weAKUnspecified, 0, hWE, hAction) = noErr) then
  1043.                     if (WEPushAction(hAction) <> noErr) then
  1044.                         ;
  1045.             end;
  1046.  
  1047. { delete current selection }
  1048.         err := _WEDeleteRange(offset, pWE^.selEnd, hWE);
  1049.         if (err <> noErr) then
  1050.             goto 1;
  1051.  
  1052. { insert a kObjectMarker character at the insertion point }
  1053.         marker := kObjectMarker;
  1054.         err := _WEInsertText(offset, @marker, 1, hWE);
  1055.         if (err <> noErr) then
  1056.             goto 1;
  1057.  
  1058. { move the insertion point after the inserted text }
  1059.         endOffset := offset + 1;
  1060.         pWE^.selStart := endOffset;
  1061.         pWE^.selEnd := endOffset;
  1062.  
  1063. { record a reference to the object descriptor in the style table }
  1064.         err := _WESetStyleRange(offset, endOffset, weDoObject, ts, hWE);
  1065.         ts.tsObject := kNullObject;
  1066.         if (err <> noErr) then
  1067.             goto 1;
  1068.  
  1069. { invalid the null style }
  1070.         BCLR(pWE^.flags, weFUseNullStyle);
  1071.  
  1072. { redraw the text }
  1073.         err := _WERedraw(offset, endOffset, hWE);
  1074.         if (err <> noErr) then
  1075.             goto 1;
  1076.  
  1077. { clear result code }
  1078.         err := noErr;
  1079.  
  1080. 1:
  1081. { return result code }
  1082.         WEInsertObject := err;
  1083.  
  1084. { clean up }
  1085.         _WEForgetHandle(ts.tsObject);
  1086.  
  1087. { unlock the WE record }
  1088.         if (_WESetHandleLock(hWE, saveWELock)) then
  1089.             ;
  1090.  
  1091.     end;  { WEInsertObject }
  1092.  
  1093.     function WEDelete (hWE: WEHandle): OSErr;
  1094.         label
  1095.             1;
  1096.         var
  1097.             pWE: WEPtr;
  1098.             hAction: WEActionHandle;
  1099.             rangeStart, rangeEnd: LongInt;
  1100.             saveWELock: Boolean;
  1101.             err: OSErr;
  1102.     begin
  1103.  
  1104. { lock the WE record }
  1105.         saveWELock := _WESetHandleLock(hWE, true);
  1106.         pWE := hWE^;
  1107.  
  1108. { return an error code if this instance is read-only }
  1109.         err := weReadOnlyErr;
  1110.         if (BTST(pWE^.flags, weFReadOnly)) then
  1111.             goto 1;
  1112.  
  1113. { stop any ongoing inline input session }
  1114.         WEStopInlineSession(hWE);
  1115.  
  1116. { get current selection range }
  1117.         rangeStart := pWE^.selStart;
  1118.         rangeEnd := pWE^.selEnd;
  1119.  
  1120. { do nothing if the selection range is empty }
  1121.         if (rangeStart < rangeEnd) then
  1122.             begin
  1123.  
  1124. { increment modification count }
  1125.                 pWE^.modCount := pWE^.modCount + 1;
  1126.  
  1127. { range extension for intelligent cut-and-paste }
  1128.                 _WEIntelligentCut(rangeStart, rangeEnd, hWE);
  1129.  
  1130. { if undo support is enabled, save the range to be deleted }
  1131.                 if (BTST(pWE^.flags, weFUndoSupport)) then
  1132.                     begin
  1133.                         WEClearUndo(hWE);
  1134.                         if (WENewAction(rangeStart, rangeEnd, 0, weAKClear, 0, hWE, hAction) = noErr) then
  1135.                             if (WEPushAction(hAction) <> noErr) then
  1136.                                 ;
  1137.                     end;
  1138.  
  1139. { delete the selection range }
  1140.                 err := _WEDeleteRange(rangeStart, rangeEnd, hWE);
  1141.                 if (err <> noErr) then
  1142.                     goto 1;
  1143.  
  1144. { reset the selection range }
  1145.                 pWE^.selStart := rangeStart;
  1146.                 pWE^.selEnd := rangeStart;
  1147.  
  1148. { redraw the text }
  1149.                 err := _WERedraw(rangeStart, rangeStart, hWE);
  1150.                 if (err <> noErr) then
  1151.                     goto 1;
  1152.  
  1153.             end;  { if non-empty selection }
  1154.  
  1155. { clear result code }
  1156.         err := noErr;
  1157.  
  1158. 1:
  1159. { return result code }
  1160.         WEDelete := err;
  1161.  
  1162. { unlock the WE record }
  1163.         if (_WESetHandleLock(hWE, saveWELock)) then
  1164.             ;
  1165.  
  1166.     end;  { WEDelete }
  1167.  
  1168.     function WECut (hWE: WEHandle): OSErr;
  1169.         label
  1170.             1;
  1171.         var
  1172.             err: OSErr;
  1173.     begin
  1174.  
  1175. { first copy... }
  1176.         err := WECopy(hWE);
  1177.         if (err <> noErr) then
  1178.             goto 1;
  1179.  
  1180. { ...then delete }
  1181.         err := WEDelete(hWE);
  1182.         if (err <> noErr) then
  1183.             goto 1;
  1184.  
  1185. { change the action kind of the most recent action, if any }
  1186.         if (hWE^^.hActionStack <> nil) then
  1187.             WEActionHandle(hWE^^.hActionStack)^^.actionKind := weAKCut;
  1188.  
  1189. { clear result code }
  1190.         err := noErr;
  1191.  
  1192. 1:
  1193. { return result code }
  1194.         WECut := err;
  1195.  
  1196.     end;  { WECut }
  1197.  
  1198.     function WECanPaste (hWE: WEHandle): Boolean;
  1199.         var
  1200.             scrapOffset: LongInt;
  1201.             objectType: OSType;
  1202.             index: Integer;
  1203.     begin
  1204.         WECanPaste := false;        { assume failure }
  1205.  
  1206.         if (not BTST(hWE^^.flags, weFReadOnly)) then
  1207.             begin
  1208.  
  1209. { return TRUE if the desk scrap contains a text flavor }
  1210.                 if (GetScrap(nil, kTypeText, scrapOffset) > 0) then
  1211.                     begin
  1212.                         WECanPaste := true;
  1213.                         Exit(WECanPaste);
  1214.                     end;
  1215.  
  1216. { see if the desk scrap contains a flavor matching one of the registered object types }
  1217.                 index := 0;
  1218.                 while (_WEGetIndObjectType(index, objectType, hWE) = noErr) do
  1219.                     begin
  1220.                         if (GetScrap(nil, objectType, scrapOffset) > 0) then
  1221.                             begin
  1222.                                 WECanPaste := true;
  1223.                                 Exit(WECanPaste);
  1224.                             end;
  1225.                         index := index + 1;
  1226.                     end;  { while }
  1227.             end;  { if not read-only }
  1228.     end;  { WECanPaste }
  1229.  
  1230.     function WEPaste (hWE: WEHandle): OSErr;
  1231.         label
  1232.             1;
  1233.         var
  1234.             hItem: Handle;
  1235.             hStyles: Handle;
  1236.             hSoup: Handle;
  1237.             selStart: LongInt;
  1238.             scrapOffset: LongInt;
  1239.             objectType: OSType;
  1240.             index: Integer;
  1241.             err: OSErr;
  1242.     begin
  1243.         hItem := nil;
  1244.         hStyles := nil;
  1245.         hSoup := nil;
  1246.         selStart := hWE^^.selStart;
  1247.  
  1248. { allocate a handle to hold a scrap item }
  1249.         err := _WEAllocate(0, kAllocTemp, hItem);
  1250.         if (err <> noErr) then
  1251.             goto 1;
  1252.  
  1253. { look for a text flavor }
  1254.         if (GetScrap(hItem, kTypeText, scrapOffset) <= 0) then
  1255.             begin
  1256.  
  1257. { no text: look for a flavor matching one of the registered object types }
  1258.                 index := 0;
  1259.                 while (_WEGetIndObjectType(index, objectType, hWE) = noErr) do
  1260.                     begin
  1261.                         if (GetScrap(hItem, objectType, scrapOffset) > 0) then
  1262.                             begin
  1263.  
  1264. { found a registered type: create a new object out of the tagged data }
  1265.                                 err := WEInsertObject(objectType, hItem, Point(0), hWE);
  1266.  
  1267. { if successful, set hItem to NIL so clean-up section won't kill the object data }
  1268.                                 if (err = noErr) then
  1269.                                     hItem := nil;
  1270.                                 goto 1;
  1271.                             end;
  1272.  
  1273. { try with next flavor }
  1274.                         index := index + 1;
  1275.                     end;  { while }
  1276.  
  1277. { nothing pasteable: return an error code }
  1278.                 err := noTypeErr;
  1279.                 goto 1;
  1280.             end;
  1281.  
  1282. { allocate a handle to hold the style scrap, if any }
  1283.         err := _WEAllocate(0, kAllocTemp, hStyles);
  1284.         if (err <> noErr) then
  1285.             goto 1;
  1286.  
  1287. { look for a 'styl' item accompanying the text }
  1288.         if (GetScrap(hStyles, kTypeStyles, scrapOffset) <= 0) then
  1289.  
  1290. { forget the handle if nothing was found or an error occurred }
  1291.             _WEForgetHandle(hStyles);
  1292.  
  1293. { allocate a handle to hold the soup, if any }
  1294.         err := _WEAllocate(0, kAllocTemp, hSoup);
  1295.         if (err <> noErr) then
  1296.             goto 1;
  1297.  
  1298. { look for a 'SOUP' item accompanying the text }
  1299.         if (GetScrap(hSoup, kTypeSoup, scrapOffset) <= 0) then
  1300.  
  1301. { forget the handle if nothing was found or an error occurred }
  1302.             _WEForgetHandle(hSoup);
  1303.  
  1304. { lock down the text }
  1305.         HLock(hItem);
  1306.  
  1307. { insert the text }
  1308.         err := WEInsert(hItem^, GetHandleSize(hItem), StScrpHandle(hStyles), hSoup, hWE);
  1309.  
  1310. 1:
  1311. { if successful, change the action kind of the most recent action, if any }
  1312.         if (err = noErr) then
  1313.             if (hWE^^.hActionStack <> nil) then
  1314.                 WEActionHandle(hWE^^.hActionStack)^^.actionKind := weAKPaste;
  1315.  
  1316. { clean up }
  1317.         _WEForgetHandle(hItem);
  1318.         _WEForgetHandle(hStyles);
  1319.         _WEForgetHandle(hSoup);
  1320.  
  1321. { return result code }
  1322.         WEPaste := err;
  1323.  
  1324.     end;  { WEPaste }
  1325.  
  1326.     function WESetStyle (mode: Integer;
  1327.                                     var ts: WETextStyle;
  1328.                                     hWE: WEHandle): OSErr;
  1329.         label
  1330.             1;
  1331.         var
  1332.             pWE: WEPtr;
  1333.             hAction: WEActionHandle;
  1334.             fontScript: ScriptCode;
  1335.             saveWELock: Boolean;
  1336.             err: OSErr;
  1337.     begin
  1338.  
  1339. { lock the WE record }
  1340.         saveWELock := _WESetHandleLock(hWE, true);
  1341.         pWE := hWE^;
  1342.  
  1343. { return an error code if this instance is read-only }
  1344.         err := weReadOnlyErr;
  1345.         if (BTST(pWE^.flags, weFReadOnly)) then
  1346.             goto 1;
  1347.  
  1348. { stop any ongoing inline input session }
  1349.         WEStopInlineSession(hWE);
  1350.  
  1351.         if (pWE^.selStart = pWE^.selEnd) then
  1352.             begin
  1353.  
  1354. { NULL SELECTION }
  1355. { first make sure the nullStyle field contains valid information }
  1356.                 _WESynchNullStyle(hWE);
  1357.  
  1358. { apply style changes to the nullStyle record }
  1359.                 _WECopyStyle(ts, pWE^.nullStyle.runStyle, pWE^.nullStyle.runStyle.tsFace, mode);
  1360.  
  1361. { if the font was altered, synchronize the keyboard script }
  1362.                 if BTST(pWE^.flags, weFNonRoman) then
  1363.                     if BTST(mode, kModeFont) then
  1364.                         begin
  1365.                             fontScript := FontToScript(pWE^.nullStyle.runStyle.tsFont);
  1366.                             if (fontScript <> GetScriptManagerVariable(smKeyScript)) then
  1367.                                 KeyScript(fontScript);
  1368.                         end;
  1369.  
  1370.             end
  1371.         else
  1372.             begin
  1373.  
  1374. { NON-EMPTY SELECTION }
  1375.  
  1376. { increment modification count }
  1377.                 pWE^.modCount := pWE^.modCount + 1;
  1378.  
  1379. { if undo support is enabled, save the styles of the text range to be affected }
  1380.                 if (BTST(pWE^.flags, weFUndoSupport)) then
  1381.                     begin
  1382.                         WEClearUndo(hWE);
  1383.                         if (WENewAction(pWE^.selStart, pWE^.selEnd, pWE^.selEnd - pWE^.selStart, weAKSetStyle, weAFDontSaveText + weAFDontSaveSoup, hWE, hAction) = noErr) then
  1384.                             if (WEPushAction(hAction) <> noErr) then
  1385.                                 ;
  1386.                     end;
  1387.  
  1388. { set the style of the selection range }
  1389.                 err := _WESetStyleRange(pWE^.selStart, pWE^.selEnd, mode, ts, hWE);
  1390.                 if (err <> noErr) then
  1391.                     goto 1;
  1392.  
  1393. { and redraw the text }
  1394.                 err := _WERedraw(pWE^.selStart, pWE^.selEnd, hWE);
  1395.                 if (err <> noErr) then
  1396.                     goto 1;
  1397.  
  1398.             end;
  1399.  
  1400. { clear the result code }
  1401.         err := noErr;
  1402.  
  1403. 1:
  1404. { unlock the WE record }
  1405.         if (_WESetHandleLock(hWE, saveWELock)) then
  1406.             ;
  1407.  
  1408. { return result code }
  1409.         WESetStyle := err;
  1410.  
  1411.     end;  { WESetStyle }
  1412.  
  1413.     function WEUseStyleScrap (hStyles: StScrpHandle;
  1414.                                     hWE: WEHandle): OSErr;
  1415.         label
  1416.             1;
  1417.         var
  1418.             pWE: WEPtr;
  1419.             saveWELock: Boolean;
  1420.             err: OSErr;
  1421.     begin
  1422.  
  1423. { lock the WE record }
  1424.         saveWELock := _WESetHandleLock(hWE, true);
  1425.         pWE := hWE^;
  1426.  
  1427. { return an error code if this instance is read-only }
  1428.         err := weReadOnlyErr;
  1429.         if (BTST(pWE^.flags, weFReadOnly)) then
  1430.             goto 1;
  1431.  
  1432. { apply the style scrap to the selection range }
  1433.         err := _WEApplyStyleScrap(pWE^.selStart, pWE^.selEnd, hStyles, hWE);
  1434.         if (err <> noErr) then
  1435.             goto 1;
  1436.  
  1437. { redraw the text }
  1438.         err := _WERedraw(pWE^.selStart, pWE^.selEnd, hWE);
  1439.  
  1440. 1:
  1441. { return result code }
  1442.         WEUseStyleScrap := err;
  1443.  
  1444. { unlock the WE record }
  1445.         if (_WESetHandleLock(hWE, saveWELock)) then
  1446.             ;
  1447.  
  1448.     end;  { WEUseStyleScrap }
  1449.  
  1450. end.